/**
 * 数据库管理模块
 * 负责数据库的初始化、加密和连接管理
 */
import { app, dialog } from 'electron'
import * as path from 'path'
import * as fs from 'fs/promises'
import Database from 'better-sqlite3-multiple-ciphers'
import keytar from 'keytar'
import crypto from 'crypto'

// 常量定义
const DB_PATH = path.join(app.getPath('userData'), 'database.sqlite')
const SERVICE_NAME = 'SpfElectronApp'
const ACCOUNT_NAME = 'database-encryption-key'
const DEFAULT_CIPHER = 'sqlcipher' // 使用sqlcipher作为默认加密方式

// 全局数据库实例
let db: Database.Database | null = null

/**
 * 安全生成256位加密密钥
 */
function generateEncryptionKey(): string {
  return crypto.randomBytes(32).toString('hex')
}

/**
 * 从系统凭证管理器获取或创建加密密钥
 */
async function getOrCreateEncryptionKey(): Promise<string> {
  try {
    let key = await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME)
    
    if (!key) {
      key = generateEncryptionKey()
      console.log('生成新加密密钥')
      await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, key)
    }
    
    return key
  } catch (error) {
    console.error('密钥管理错误:', error)
    throw new Error('无法获取加密密钥')
  }
}

/**
 * 检查数据库是否存在
 */
async function databaseExists(): Promise<boolean> {
  return fs.access(DB_PATH).then(() => true).catch(() => false)
}

/**
 * 检查数据库是否已加密
 */
async function isDatabaseEncrypted(): Promise<boolean> {
  try {
    // 检查数据库文件是否存在
    if (!await databaseExists()) {
      return false
    }
    
    // 尝试无密钥打开数据库
    try {
      const testDb = new Database(DB_PATH)
      
      try {
        // 尝试读取数据库结构
        testDb.prepare('SELECT name FROM sqlite_master LIMIT 1').get()
        // 如果成功读取，说明未加密
        testDb.close()
        return false
      } catch (err) {
        // 读取失败，可能已加密
        testDb.close()
        return true
      }
    } catch (err) {
      // 打开失败，假设已加密
      return true
    }
  } catch (error) {
    console.error('加密状态检查失败:', error)
    return false
  }
}

/**
 * 创建新的加密数据库
 */
async function createEncryptedDatabase(key: string): Promise<void> {
  try {
    console.log('创建新的加密数据库...')
    const newDb = new Database(DB_PATH)
    
    // 设置加密方式
    newDb.pragma(`cipher='${DEFAULT_CIPHER}'`)
    
    // 加密数据库
    newDb.pragma(`rekey='${key}'`)
    
    // 启用WAL模式提高性能
    newDb.pragma('journal_mode = WAL')
    
    // 创建项目表
    newDb.exec(`
      CREATE TABLE IF NOT EXISTS project (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name VARCHAR(100) NOT NULL,
        description TEXT,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `)
    
    newDb.close()
    console.log('新数据库已加密并创建表结构')
  } catch (error) {
    console.error('创建加密数据库失败:', error)
    throw error
  }
}

/**
 * 删除现有数据库并创建新的加密数据库
 */
async function recreateEncryptedDatabase(key: string): Promise<void> {
  // 如果数据库存在，先备份
  if (await databaseExists()) {
    const backupPath = `${DB_PATH}.backup.${Date.now()}.db`
    await fs.copyFile(DB_PATH, backupPath)
    console.log('已备份原数据库:', backupPath)
    
    // 删除原数据库
    await fs.unlink(DB_PATH)
    console.log('已删除原数据库')
  }
  
  // 创建新的加密数据库
  await createEncryptedDatabase(key)
}

/**
 * 创建加密数据库连接
 */
async function createEncryptedConnection(key: string): Promise<Database.Database> {
  const newDb = new Database(DB_PATH);
  
  // 设置加密方式
  newDb.pragma(`cipher='${DEFAULT_CIPHER}'`);
  
  // 设置密钥
  newDb.pragma(`key='${key}'`);
  
  // 启用WAL模式
  newDb.pragma('journal_mode = WAL');
  
  return newDb;
}

/**
 * 初始化数据库
 */
export async function initDatabase(): Promise<Database.Database> {
  try {
    console.log('初始化数据库...')
    console.log('数据库路径:', DB_PATH)
    
    // 获取加密密钥
    const key = await getOrCreateEncryptionKey()
    
    // 检查数据库是否存在
    const exists = await databaseExists()
    console.log('数据库是否存在:', exists)
    
    if (exists) {
      // 检查数据库是否已加密
      const encrypted = await isDatabaseEncrypted()
      console.log('数据库是否已加密:', encrypted)
      
      // 如果未加密，删除并重新创建
      if (!encrypted) {
        console.log('检测到未加密数据库，重新创建...')
        await recreateEncryptedDatabase(key)
      }
    } else {
      // 数据库不存在，创建新的加密数据库
      await createEncryptedDatabase(key)
    }
    
    // 创建加密连接
    db = await createEncryptedConnection(key);
    console.log('数据库初始化成功')
    
    // 再次验证数据库加密状态
    if (!await isDatabaseEncrypted()) {
      console.error('错误: 数据库未能正确加密!')
      throw new Error('数据库加密失败')
    }
    
    return db
    
  } catch (error) {
    console.error('数据库初始化失败:', error)
    
    // 尝试恢复
    try {
      const result = await dialog.showMessageBox({
        type: 'error',
        title: '数据库错误',
        message: '数据库初始化失败，是否重置数据库？',
        detail: String(error),
        buttons: ['重置', '退出'],
        defaultId: 1,
        cancelId: 1
      })
      
      if (result.response === 0) {
        // 用户选择重置
        await recreateEncryptedDatabase(await getOrCreateEncryptionKey())
        
        // 重新创建连接
        db = await createEncryptedConnection(await getOrCreateEncryptionKey())
        console.log('数据库重建成功')
        
        return db
      } else {
        // 用户选择退出
        app.quit()
        throw new Error('用户取消重建数据库')
      }
    } catch (recoveryError) {
      console.error('数据库恢复失败:', recoveryError)
      app.quit()
      throw new Error('数据库恢复失败')
    }
  }
}

/**
 * 项目类型定义
 */
export interface Project {
  id?: number;
  name: string;
  description?: string;
  createdAt?: Date;
  updatedAt?: Date;
}

/**
 * 获取所有项目
 */
export function getAllProjects(): Project[] {
  if (!db) {
    throw new Error('数据库未初始化')
  }
  
  const stmt = db.prepare(`
    SELECT id, name, description, created_at as createdAt, updated_at as updatedAt
    FROM project
    ORDER BY updated_at DESC
  `)
  
  return stmt.all() as Project[]
}

/**
 * 根据ID获取项目
 */
export function getProjectById(id: number): Project | undefined {
  if (!db) {
    throw new Error('数据库未初始化')
  }
  
  const stmt = db.prepare(`
    SELECT id, name, description, created_at as createdAt, updated_at as updatedAt
    FROM project
    WHERE id = ?
  `)
  
  return stmt.get(id) as Project | undefined
}

/**
 * 创建新项目
 */
export function createProject(project: Project): Project {
  if (!db) {
    throw new Error('数据库未初始化')
  }
  
  const stmt = db.prepare(`
    INSERT INTO project (name, description)
    VALUES (?, ?)
  `)
  
  const result = stmt.run(project.name, project.description || null)
  
  return {
    ...project,
    id: result.lastInsertRowid as number
  }
}

/**
 * 更新项目
 */
export function updateProject(id: number, project: Partial<Project>): boolean {
  if (!db) {
    throw new Error('数据库未初始化')
  }
  
  // 检查项目是否存在
  const existing = getProjectById(id)
  if (!existing) {
    return false
  }
  
  const stmt = db.prepare(`
    UPDATE project
    SET name = ?, description = ?, updated_at = CURRENT_TIMESTAMP
    WHERE id = ?
  `)
  
  const result = stmt.run(
    project.name || existing.name,
    project.description !== undefined ? project.description : existing.description,
    id
  )
  
  return result.changes > 0
}

/**
 * 删除项目
 */
export function deleteProject(id: number): boolean {
  if (!db) {
    throw new Error('数据库未初始化')
  }
  
  const stmt = db.prepare('DELETE FROM project WHERE id = ?')
  const result = stmt.run(id)
  
  return result.changes > 0
}

/**
 * 验证数据库是否已加密
 */
export async function verifyDatabaseEncryption(): Promise<boolean> {
  return await isDatabaseEncrypted()
}

/**
 * 关闭数据库连接
 */
export async function closeDatabase(): Promise<void> {
  if (db) {
    db.close()
    db = null
    console.log('数据库连接已关闭')
  }
}

// 应用退出时关闭数据库连接
app.on('quit', () => {
  closeDatabase().catch(console.error)
})